;;; appyaml-mode.el --- mode for google's app.yaml

;; Copyright (C) 2011 zxy
;; Author: zxy <gcoordinate@gmail.com>
;; Maintainer: zxy <gcoordinate@gmail.com>
;; Created: Dec 2011
;; Version: 1.3.1

;;
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 3 of the License, or
;; (at your option) any later version.
;;
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;; GNU General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
;; along with this program; see the file COPYING.  If not, write to
;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
;; Boston, MA 02111-1307, USA.

;; Installation instructions
;; --------------------------------
;; (setq gae-python-root-path (concat program-path"google_appengine/"))
;; (add-to-list 'load-path (concat plugin-path "appengine-emacs-toolkit"))
;; (require 'appyaml-mode)
;; (add-hook 'appyaml-mode-hook
;;           (lambda ()
;;             (progn (local-set-key "\C-cc" 'gae-python-start-appserver)
;;                    (local-set-key "\C-cb" 'appengine-browse-appserver)
;;                    (local-set-key "\C-cu" 'gae-python-update-appserver))))
;;
;; ;; if you use python27
;; (setq gae-priority-python-version "27")

(load-file (replace-regexp-in-string "appyaml-mode.el" "appengine-common.el" load-file-name))
(load-file (replace-regexp-in-string "appyaml-mode.el" "appengine-django.el" load-file-name))
(message (concat "Loading " load-file-name))

;; public var

(defvar gae-python-root-path nil
  "*path of gae")

(defvar gae-priority-python-version "25"
  "*Priority python version")

(defvar gae-template-directory-python27
  (concat (file-name-directory (or load-file-name buffer-file-name))"new_project_template_gae_python27")
  "*Project template for python27")

;; private var

(defun* gae-python-start-appserver (&optional (port nil))
  "Open shell to start gae appserver"
  (interactive)
  (unless (and (not (equal nil gae-python-root-path))
               (file-exists-p gae-python-root-path))
    (error "[appengine] Cannot find gae-python-root-path."))
  (save-buffer buffer-file-name)
  (if (eq nil port)
      (progn
        (appengine-check-server-hash buffer-file-name)
        (setq port appengine-server-port)))
  (setq bufname (concat "*gae-appserver-"port"*"))
  (if (not (eq nil (get-buffer bufname)))
      (kill-buffer bufname))
  (setq proname (replace-regexp-in-string "app.yaml" "" buffer-file-name))
  (shell bufname)
  (comint-send-string (current-buffer) (concat "echo '[appengine] AppServer Starting "proname"...' \n"))
  (if (eq system-type 'windows-nt)
      (comint-send-string (current-buffer) (concat "python \""gae-python-root-path"/dev_appserver.py\" --port="port" \""proname"\" \n"))
    (comint-send-string (current-buffer) (concat "python \""gae-python-root-path"/dev_appserver.py\" --port="port" \""proname"\" \n")))
  (end-of-buffer)
  (other-window -1))

(defun gae-python-update-appserver ()
  "Update appserver"
  (interactive)
  (unless (and (not (equal nil gae-python-root-path))
               (file-exists-p gae-python-root-path))
    (error "[appengine] Cannot find gae-python-root-path."))
  (save-some-buffers)
  (setq proname (replace-regexp-in-string "app.yaml" "" buffer-file-name))
  (shell "*appengine-temp*")
  (comint-send-string (current-buffer) (concat "echo '[appengine] AppServer Updateing "proname"...' \n"))
  (if (eq system-type 'windows-nt)
      (comint-send-string (current-buffer) (concat "python \""gae-python-root-path"/appcfg.py\" update \""proname"\" \n"))
    (comint-send-string (current-buffer) (concat "python \""gae-python-root-path"/appcfg.py\" update \""proname"\" \n")))
  (end-of-buffer)
  (other-window -1))

;; For project

(defun gae-python-create-project (projectpath projectname pythonver)
  "Create new project"
  (setq gae-template-directory (concat gae-python-root-path"/new_project_template"))
  (when (equal pythonver "27")
    (setq gae-template-directory gae-template-directory-python27))
  (unless (and (not (equal nil gae-template-directory))
               (file-exists-p gae-template-directory))
    (error "[appengine] Cannot find gae template directory!"))
  (copy-directory gae-template-directory projectpath)
  (find-file (concat projectpath"/app.yaml"))
  (beginning-of-buffer)
  (replace-string "new-project-template" projectname)
  (beginning-of-buffer)
  (save-buffer buffer-file-name))

(defun gae-python-new-project ()
  "Create new project"
  (unless (and (not (equal nil gae-python-root-path))
               (file-exists-p gae-python-root-path))
    (error "[appengine] Cannot find gae-python-root-path."))
  (interactive)
  (if (equal nil buffer-file-name)
      (setq tmpprojectpath "~/")
    (setq tmpprojectpath (file-name-directory buffer-file-name)))
  ;; read information from mini buffer
  (let ((projectpath (read-string "[appengine] Project path: "
                                  tmpprojectpath nil tmpprojectpath nil))
        (projectname (read-string "[appengine] Project name (default gae-python-project): "
                                  nil nil "gae-python-project" nil))
        (pythonver (read-string (format "[appengine] Python version (default %s): " gae-priority-python-version)
                                nil nil gae-priority-python-version nil)))
    (setq projectpath (concat projectpath"/"projectname))
    (unless (or (equal pythonver "25") (equal pythonver "27"))
      (setq pythonver gae-priority-python-version))
    (message "[appengine] Building python%s project at %s." pythonver projectpath)
    (when (and (file-exists-p projectpath) (file-exists-p (concat projectpath"/app.yaml")))
      (find-file (concat projectpath"/app.yaml"))
      (error "[appengine] Project exist!"))
    (if (or (not (file-exists-p projectpath))
            (and (file-exists-p projectpath)
                 (y-or-n-p (format "[appengine] Folder %s exist! Overwrit?" projectpath))))
        (gae-python-create-project projectpath projectname pythonver))
    ))

;; define the major mode.

(define-derived-mode appyaml-mode makefile-mode "appyaml"
  "appyaml-mode is a major mode for google app engine app.yaml file."
  )

(add-to-list 'auto-mode-alist '("\\app.yaml\\'" . appyaml-mode))

(provide 'appyaml-mode)

;;; appyaml-mode.el ends here